﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace GameStateManagement
{
    public class Sphere : DrawableObject//Microsoft.Xna.Framework.DrawableGameComponent
    {

        protected Utils.Timer timers;
        public float fShrinkForce;
        public float fGrowForce;
        public float fDeathForce;

        public SoundEffect inflating;

        public Target target;

        //protected bool followCam;
        protected bool first;

       // protected Game game;
        public Sphere(Game game)
            : base(game)
        {
            this.game = (GameStateManagementGame)game;
            timers = new Utils.Timer();
            worldTransformMatrix = Matrix.Identity;
            vWorldPosition = new Vector3(0.0f, 0.0f, 0.0f);
            qRotation = Quaternion.Identity;
            fScale = 2.5f;

            first = false;
            hasChanged = true;
            followCam = true;

            inflating = GameplayScreen.content.Load<SoundEffect>("inflate");

            fShrinkForce = 6.0f;
            fGrowForce = 0.0f;
            fDeathForce = 0.0f;


            //radScale = 13.5f;

            
        }

        public override void Initialize()
        {
            target = new Target(game);
            base.Initialize();
            

        }

        public float Scale
        {
            get { return fScale; }
            set
            {
                fScale = value;
                hasChanged = true;
            }
        }

        public Vector3 Position
        {
            get { return vWorldPosition; }
            set
            {
                vWorldPosition = value;
                hasChanged = true;
            }
        }

        public Quaternion Rotation
        {
            get { return qRotation; }
            set { qRotation = value; }
        }

        public void switchCam()
        {
            followCam = !followCam;
            target.followCam = this.followCam;
        }

       /* public void updateWorldTransformMatrix()
        {
            Matrix scaleMatrix = Matrix.CreateScale(fScale);
            Matrix rotationMatrix = Matrix.CreateFromQuaternion(qRotation);
            Matrix translationMatrix = Matrix.CreateTranslation(vWorldPosition);

            worldTransformMatrix = scaleMatrix;
            worldTransformMatrix *= rotationMatrix;
            worldTransformMatrix *= translationMatrix;

            WorldBounds.Center = vWorldPosition;
            WorldBounds.Radius = ModelBounds.Radius * fScale;

            
        }*/

        public override void Update(GameTime gameTime)
        {
            float dTime = ((float)gameTime.ElapsedGameTime.Ticks / System.TimeSpan.TicksPerMillisecond / 1000.0f);
            if (first)
            {
                updateWorldTransformMatrix();
                Random random = new Random();
                float fzAngle, fyAngle;
                fzAngle = (float)(random.NextDouble() * Math.PI);
                fyAngle = (float)(random.NextDouble() * Math.PI);

                float x = getRadius() * (float)(Math.Sin(fyAngle) * Math.Sin(fzAngle));
                float y = getRadius() * (float)Math.Cos(fyAngle);
                float z = getRadius() * (float)(Math.Sin(fyAngle) * Math.Cos(fzAngle));

                Vector3 pos = new Vector3(x, y, z);

                target.Position = pos;
                target.followCam = this.followCam;
                target.updateRotation();

                game.Components.Add(target);
                first = false;
            }


            if (this.getRadius() <= 450.0f)
            {
                this.Scale = this.Scale - (fShrinkForce - fGrowForce - fDeathForce) * dTime * 0.01f;
            }
            updateWorldTransformMatrix();
            if (!target.death)
            {
                Vector3 oldTargetPos = target.Position;
                oldTargetPos.Normalize();
                oldTargetPos *= getRadius();
                target.Position = oldTargetPos;
            }
            if (target.revive)
            {
                if (target.Position.Length() >= 0.9f * this.getRadius())
                {
                    Vector3 oldTargetPos = target.Position;
                    oldTargetPos.Normalize();
                    oldTargetPos *= getRadius();
                    target.Position = oldTargetPos;
                    target.revive = false;
                    target.death = false;
                }
            }
  
            
            timers.Update(gameTime);
            base.Update(gameTime);
        }

        public float getRadius()
        {
            //return this.WorldBounds.Radius;
            return this.WorldBounds.Radius * 13.5f;
        }

        public void hitSphere()
        {

            fShrinkForce = 8.0f;
            timers.AddTimer("sphereHitTimer", 0.2f, new Utils.TimerDelegate(ResetShrink), false);

        }
        void ResetShrink()
        {
            fShrinkForce = 6.0f;
        }

        void ResetForce()
        {
            fGrowForce = 0.0f;
        }
        void ResetDeath()
        {
            fDeathForce = 0.0f;
        }

        public void hitTarget()
        {
            if (!target.death)
            {
                fGrowForce = 13.0f;
                timers.AddTimer("targetHitTimer", 0.2f, new Utils.TimerDelegate(ResetForce), false);

                target.numHits = target.numHits - 1;
                if (target.numHits == 0)
                {
                    target.numHits = 20;
                    fDeathForce = 70.0f;
                    timers.AddTimer("deathTimer", 0.8f, new Utils.TimerDelegate(ResetDeath), false);
                    target.deathStart();
                    inflating.Play(1.0f);
                }
                target.hit();
            }
        }

        protected override void LoadContent()
        {
            contentManager = new ContentManager(Game.Services, "Content");
            actorModel = contentManager.Load<Model>("bubble");
            actorBones = new Matrix[actorModel.Bones.Count];
            celShader = contentManager.Load<Effect>("CelShader");
            texture = contentManager.Load<Texture2D>("testPink");
            celShader.Parameters["Texture"].SetValue(texture);
            celShader.Parameters["textureEnabled"].SetValue(true);
            
            float[] temp = new float[2] { 16.0f, 0.01f };
            celShader.Parameters["toonThresholds"].SetValue(temp);
            temp = new float[3] { 1.1f, 0.6f, 0.4f };
            celShader.Parameters["toonBrightnessLevels"].SetValue(temp);
         
            changeEffectUsedByModel(actorModel, celShader);


            base.LoadContent();
            
            foreach (ModelMesh mesh in actorModel.Meshes)
            {
                ModelBounds = BoundingSphere.CreateMerged(ModelBounds,
                mesh.BoundingSphere);
            }

            first = true;


        }

        protected override void UnloadContent()
        {
            contentManager.Unload();
            base.UnloadContent();
        }

       /* public override void Draw(GameTime gameTime)
        {
            if (hasChanged)
            {
                updateWorldTransformMatrix();
                hasChanged = false;
            }


            

            GraphicsDevice.RenderState.DepthBufferEnable = true;
            actorModel.CopyAbsoluteBoneTransformsTo(actorBones);
            foreach (ModelMesh mesh in actorModel.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.World =
                    actorBones[mesh.ParentBone.Index] * worldTransformMatrix;
                    if (followCam)
                    {
                        effect.View = GameplayScreen.camera.View;
                        effect.Projection = GameplayScreen.camera.Projection;
                    }
                    else
                    {
                        effect.View = GameplayScreen.CameraMatrix;
                        effect.Projection = GameplayScreen.ProjectionMatrix;
                    }
                    effect.EnableDefaultLighting();
                    effect.PreferPerPixelLighting = true;
                    effect.AmbientLightColor = GameplayScreen.ambientLightColor;
                    effect.DirectionalLight0.DiffuseColor = GameplayScreen.diffuseColor;
                    effect.DirectionalLight0.Direction = GameplayScreen.diffuseDirection;
                    effect.SpecularColor = GameplayScreen.specularColor;
                    effect.SpecularPower = GameplayScreen.specularPower;

                }
                mesh.Draw();
            }
            base.Draw(gameTime);
        }*/


    }
}
